<template>
  <!-- 入口-->
  <div class="div_custome_close">
    <!--    这里是自定义关闭烂.-->
  </div>
  <div style="display: inline-block" class="div_close_narrow">
    <div class="div_close" @click="windowClose">
      <el-icon size="30">
        <Close/>
      </el-icon>
    </div>
    <div class="div_narrow" @click="windowNarrow">
      <el-icon size="30">
        <Minus/>
      </el-icon>
    </div>
  </div>
  <div style="-webkit-user-select: none">
    <Register v-if="this.$store.state.winStatu === -1"/>
    <Login v-if="this.$store.state.winStatu ===  0"></Login>
    <Main v-if="this.$store.state.winStatu === 1"></Main>
    <!--    router-view 其实应该在页面进行替换的时候进行展示,或者说就是全部使用状态码来进行展示或者替换.-->
  </div>
</template>

<script>

import Login from './components/login'
import Main from './components/main'
import Register from './components/register'
import {WsAddr} from "./config/config"
import {WaterAudio} from "./util/audio"
import {ipcRenderer} from "electron"
import {Close, Minus} from '@element-plus/icons'
import {Timeout} from "./util/timeout"
import {request} from "./util/httprequest";

export default {
  name: 'App',
  components: {Login, Main, Register, Close, Minus},
  data() {
    return {
      winState: this.$store.state.winStatu,
      ws: {},
      data: {},
      testData: {
        a: "",
        b: "",
      }
    }
  },

  methods: {

    windowNarrow() {
      // 还不知道怎么做....
      console.log("windowNarrow")
      ipcRenderer.send('windowNarrow', "1")
    },

    windowClose() {
      console.log("start windowClose")
      // 通知主进程进行程序关闭.
      if (this.$store.state.userInfo.login_account_string !== "") {
        // 1、下线通知.
        // 需要进行广播.
        // 不需要message.
        let dataJson = {
          "fid": this.$store.state.userInfo.id,
          "uid": this.$store.state.userInfo.id,
          "tid": -1,
          "type": 3,
          "sid": this.$store.state.chartStatus.nowSessions[this.$store.state.chartStatus.nowChartNumber].id,
          "msg": "",
          "seq": -1,
          "ack": 99,
          "body": "",
          "s_type": 0,
          "gid": -1,
          "img_url": "",
          "username": "",
        }
        // // 需要校验一下ws状态.
        // if (this.ws.readyState === 1) {
        //   console.log("readyState === 1")
        // ws 打开的时候才需要进行发送.

        console.log("off line send data")
        console.log(dataJson)
        this.ws.send(JSON.stringify(dataJson))
        // 2、修改当前在线状态.
        request("get", "/user/offline?login_account_string=" + this.$store.state.userInfo.login_account_string)
            .then(() => {
              // 不管下线成功还是失败,直接quic.
              // ipcRenderer.send('windowCustomClose', '1')
            })
      }
      setTimeout(() => {
        ipcRenderer.send('windowCustomClose', '1')
      }, 600)
      // ipcRenderer.send('windowCustomClose', '1')
    },

    connectionWs() {
      // todo: 这里不应该直接使用静态的WsAddr,应该从后台获取.

      this.ws = new WebSocket(WsAddr)
      this.ws.onmessage = this.onmessage
      this.ws.onopen = function (event) {
        console.log("start onopen event: ", event)
        // 当成功打开的时候进行消息SaveSession操作.
      }

      this.ws.onclose = function (event) {
        console.log("onclose event: ", event)
      }

      this.ws.onerror = function (event) {
        console.log("onerror event: ", event)
      }
    },

    // 从服务端接受到消息.
    onmessage(message) {
      // 声音提示.

      console.log("server msg : " + message.data)
      let obj = eval('(' + message.data + ')')
      // obj 就是后台传过来的JSON数据.
      if (obj.type === 1) {

        WaterAudio()
        // 1 表示是普通消息.

        this.$store.commit('setAddMessage', obj)
        // 向IMCoreServer进行ACK应答.表示B(我)已经收到当前这个消息了.
        obj.type = 5
        // 确认收到.
        obj.ack = 1
        // 还是把tid和uid原封不动的发送过去.
        console.log("to a ack")
        console.log(obj)
        this.ws.send(JSON.stringify(obj))
      } else if (obj.type === 2) {
        // 上线提醒.
        WaterAudio()
        this.$store.commit('userLoginNotify', obj)
      } else if (obj.type === 3) {
        // 好友下线通知.
        this.$store.commit('friendOffLineNotify', obj)
      } else if (obj.type === 4) {
        // Client 消息持久化失败.
      } else if (obj.type === 6) {
        // 接受到群聊中的消息.
        WaterAudio()
        this.$store.commit('setAddMessage', obj)
      } else if (obj.type === 5 || obj.type === 21) {
        // ACK.
        // 2、根据seq定位到消息,这里定位一定要Message的Uid是当前用户才可.
        this.$store.state.chartStatus.nowSessions.filter((value) => {
          if (value.id === obj.sid) {
            // 1、根据sid 找到当前的session.
            value.array_message.filter((mv) => {
              // 这里的mv应该在和sendMessage哪里的dataJson是一个引用.
              if (mv.uid === obj.uid && mv.seq === obj.seq) {
                // 如果要查看ACK是否成功,这里改下ACK状态即可,但是之后需要改回来.
                // mv.ack = -1
                // 更新ack.
                mv.ack = 1
                // 正常的情况下，离线消息如果能打印出这句话意味着OK.
                console.log(" onmessage ack 成功.")
              }
            })
          }
        })
      }
    },
  },

  mounted() {
  },
  computed: {
    winSta() {
      return this.$store.state.winStatu
    },
    nowMessage() {
      return this.$store.state.nowMessage
    }
  },

  created() {
    request("get","/schedule").then((response)=>{
      console.log("schedule response: ",response)
    })
  },

  watch: {
    nowMessage(newValue) {
      if (newValue !== "") {
        let dataJson = {
          "uid": this.$store.state.userInfo.id,
          "tid": -1,
          "type": 1,
          "fid": -1,
          "sid": -1,
          "body": newValue,
          "seq": 0,
          "ack": 0, // 初始化0(要考虑登录之后ack默认零值得情况).
          "s_type": 0,  // 0是单聊,默认是单聊.
          "gid": -1,
          "img_url": "",
          "username": "",
        }
        if (newValue === "**&&^^%%^^&&**") {
          dataJson.type = -1
          setTimeout(() => {
            this.ws.send(JSON.stringify(dataJson))
          }, 1200)
        } else {

          // 说明要发送的消息.
          // tid目标人,这里如果是群的话,应该是群id.
          let session = this.$store.state.chartStatus.nowSessions[this.$store.state.chartStatus.nowChartNumber]
          dataJson.tid = this.$store.state.chartStatus.nowSessionInfo.uid
          if (session.s_type === 1) {
            // 群聊.
            dataJson.gid = session.gid
            dataJson.type = 6
            dataJson.s_type = 1
            dataJson.img_url = this.$store.state.userInfo.img_url
            dataJson.username = this.$store.state.userInfo.username
          }
          dataJson.sid = session.id
          dataJson.ack = 0
          // 设置seq.
          let seq = this.$store.state.userInfo.seq + 1
          this.$store.state.userInfo.seq++
          dataJson.seq = seq
          console.log("send message")
          console.log(dataJson)
          this.ws.send(JSON.stringify(dataJson))

          // 将当前发送的消息添加到当前session中的array_message中.
          if (this.$store.state.chartStatus.nowSessions[this.$store.state.chartStatus.nowChartNumber].array_message === null) {
            this.$store.state.chartStatus.nowSessions[this.$store.state.chartStatus.nowChartNumber].array_message = []
          }
          this.$store.state.chartStatus.nowSessions[this.$store.state.chartStatus.nowChartNumber].array_message.push(dataJson)
          // 发送之后
          this.$store.state.ackQueue.set(dataJson, Timeout((queue, message) => {
            console.log("3S 之后ACK检查")
            // 3S之后如果还没有Ack，则提示当前用户表示消息未发送过去.
            // 重传一次就可以了.
            if (message.ack === 0) {
              console.log("3S 之后ACK检查 message.ack 还是0 进行重发.")
              // 还没有进行ack.
              // message.ack = -1
              // 重新发送,并且重新计时.
              this.ws.send(JSON.stringify(message))
              setTimeout(() => {
                console.log("重发的超时校验.")
                if (message.ack === 1) {
                  // 成功ACK.
                  queue.delete(message)
                } else {
                  message.ack = -2
                }
              }, 3000)
            } else if (message.ack === 1) {
              // B ACK成功.
              // 从队列中剔除.
              console.log("消息sid " + message.sid + " seq: " + message.seq + "  ack  success")
              queue.delete(message)
            } else if (message.ack === -1) {
              console.log("3S之后设置ack 为-2 意味手动重新发送")
              // IMCoreServer没有收到ACK.
              // 这里手动设置ACK为-2.意味Client不会帮助你重新发送,需要自己点击鼠标进行重新发送.
              message.ack = -2
            }
          }, this.$store.state.ackQueue, dataJson, 3000))
        }
      }
      this.$store.commit('clearMessage')
    }
  }

  // winSta(nv) {
  //   if (nv === 1) {
  //     // TODO: 建立链接.
  //     this.ws = new WebSocket(WsAddr)
  //     this.ws.onmessage = function (message) {
  //       // 从服务端接受到消息.
  //       console.log("server msg1 : " + message.data)
  //       // 正常.
  //       let strData = eval('(' + message.data + ')')
  //       console.log(strData)
  //       // 坏了 这里如何进行更新呢?
  //       console.log(this.$store.state.chartStatus)
  //     }
  //     this.ws.onopen = function (event) {
  //       console.log("start onopen event: ", event)
  //     }
  //
  //     this.ws.onclose = function (event) {
  //       console.log("onclose event: ", event)
  //     }
  //
  //     this.ws.onerror = function (event) {
  //       console.log("onerror event: ", event)
  //     }
  //   }
  // },
  // 监听state中的nowMessage.

}
</script>

<style>
/*  padding内边距 margin外边距*/
/*定义拖拽*/
.div_custome_close {
  position: absolute;
  height: 30px;
  width: 1290px;
  -webkit-app-region: drag;
  /* 禁止用于使用鼠标选中文字.*/
  -webkit-user-select: none;
  /*float: right;*/
}

/*定义关闭按钮>*/
.div_close_narrow {
  z-index: 9999999999;
  position: absolute;
  margin-left: 1320px;
}

.div_narrow {
  display: inline-block;
  float: right;
  transition: all 0.6s;
}

.div_close {
  display: inline-block;
  float: right;
  margin-right: 15px;
  margin-left: 20px;
  transition: all 0.6s;
}

div[class="div_narrow"]:hover {
  cursor: pointer;
  transform: scale(1.4);
}

div[class="div_close"]:hover {
  cursor: pointer;
  transform: scale(1.4);
}


</style>
